//====================================================================
// Author: Jason Plante
// Date Created: 29 October 2007
// LINQ to Lucene: Copyright (c) 2007.  All rights reserved.
//====================================================================

using System;
using System.Threading;
using Lucene.Linq.VSTests.Helpers;
using Lucene.Net.Analysis;
using Lucene.Net.Store;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Lucene.Linq.VSTests
{
    [TestClass] // Description("IndexContext unit tests")]
    public class TestIndexContext
    {
        #region asserters

        private void AssertSetUp(IndexContext ic)
        {
        }

        #endregion

        #region ctor

        [TestMethod, ExpectedException(typeof (ArgumentNullException))]
        public void Null_directory_should_throw()
        {
            var ic = new IndexContext(null, new SimpleAnalyzer());
        }

        [TestMethod, ExpectedException(typeof (ArgumentNullException))]
        public void Null_analyzer_should_throw()
        {
            new IndexContext(new RAMDirectory(), null);
        }

        #endregion

        #region disposal

        [TestMethod]
        public void Disposal_clears_everything()
        {
            IndexContext i = null;

            using (i = new IndexContext(new RAMDirectory(), new SimpleAnalyzer()))
            {
                Assert.IsNotNull(i.Searcher);
                Assert.IsNotNull(i.Modifier);
            }

            Assert.IsNull(i.Searcher);
            Assert.IsNull(i.Modifier);
        }

        #endregion

        #region modifying locker

        [TestMethod]
        public void Acquiring_read_lock_should_keep_writer_out()
        {
            var rd = new RAMDirectory();
            using (var i = new IndexContext(rd, new SimpleAnalyzer()))
            {
                bool passed = false;
                var task = new ThreadRunner(new Action(() =>
                                                           {
                                                               using (i.EnterWriteLock())
                                                               {
                                                                   passed = true;
                                                               }
                                                           }));

                IDisposable rl = i.EnterReadLock();
                task.Run();
                Thread.Sleep(50);
                Assert.AreEqual(passed, false);
                rl.Dispose();
                Thread.Sleep(50);
                Assert.AreEqual(passed, true);
            }
        }

        [TestMethod]
        public void Acquiring_write_lock_should_keep_reader_out()
        {
            using (var i = new IndexContext(new RAMDirectory(), new SimpleAnalyzer()))
            {
                bool passed = false;

                var tr = new Thread(() =>
                                        {
                                            using (i.EnterReadLock())
                                            {
                                                passed = true;
                                            }
                                        });

                IDisposable writeLock = i.EnterWriteLock();
                tr.Start();
                Thread.Sleep(100);
                Assert.AreEqual(passed, false);
                writeLock.Dispose();
                Thread.Sleep(100);
                Assert.AreEqual(passed, true);
            }
        }

        #endregion
    }
}